/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <atomic>
#include <memory>
#include <thread>
#include <string>
#include <fstream>
#include <mutex>
#include "utils_noncopyable.h"
#include "common_media_define.h"
#include "media_frame.h"
#include "utils_callback_list.h"
#include "hal_audio.h"
#include "utils_block_queue.h"

namespace El {
namespace Media {

const int32_t kAudioBufferSize = 160;
const size_t kDefaultAudioStreamQueueCapacity = 20; // Added for stream queue capacity

class Speak {
    DISALLOW_COPY_AND_MOVE(Speak);

public:
    /**
     * @brief 获取 Speak 类的单例实例。
     * @return Speak 类的单例实例的引用。
     */
    static Speak &GetInstance();

    /**
     * @brief Speak 类的构造函数。
     */
    Speak();

    /**
     * @brief Speak 类的析构函数。
     */
    ~Speak();

    /**
     * @brief 初始化 Speak 服务，加载配置并应用到 HAL。
     * @return 如果成功初始化，则返回 true；否则返回 false。
     */
    bool Start();

    /**
     * @brief 开始播放音频文件。
     * @param path 音频文件的路径。
     * @param repeatCount 重复播放次数。默认为1。如果为0，则表示无限循环播放。
     * @param adecConfig 音频解码器配置，默认为nullptr使用系统默认配置。
     * @return 如果成功开始播放，则返回 true；否则返回 false。
     */
    bool StartFilePlay(const char *path, int32_t repeatCount = 1, const HAL_ADEC_COM_CONFIG_S *adecConfig = nullptr);

    /**
     * @brief 开始流式播放音频。
     * @param adecConfig 音频解码器配置。
     * @return 如果成功开始流式播放，则返回 true；否则返回 false。
     */
    bool StartStreamPlay(const HAL_ADEC_COM_CONFIG_S &adecConfig);

    /**
     * @brief 推送音频数据进行播放。
     * @param data 指向音频数据的指针。
     * @param size 音频数据的大小。
     * @param useBlockingMode 是否使用阻塞模式。true表示直接调用HAL接口阻塞发送，false表示通过队列异步发送（默认）。
     * @return 如果成功将数据推入队列或发送到HAL，则返回 true；否则返回 false。
     * @note 非阻塞模式下，队列推送超时时间固定为100毫秒。
     */
    bool PushAudioData(const char *data, size_t size, bool useBlockingMode = true);

    /**
     * @brief 停止播放，无论是文件播放还是流式播放。
     */
    void Stop();    /**
    
     * @brief 设置音量。
     * @param volume 要设置的音量值。
     * @return 如果成功设置音量，则返回 true；否则返回 false。
     */
    bool SetVolume(int32_t volume);

    /**
     * @brief 获取当前音量。
     * @return 返回当前音量值 (0-100)。如果未配置或获取失败，则返回默认值。
     */
    int32_t GetVolume() const;

    /**
     * @brief 获取当前播放的文件路径。
     * @return 当前播放的文件路径，如果没有播放文件则返回空字符串。
     */
    std::string GetCurrentFilePath() const;
    
private:
    /**
     * @brief 统一的音频播放线程函数。
     */
    void PlayThread();
    
    /**
     * @brief 从文件读取音频数据并放入队列
     */
    void ReadFileToQueue();

private:
    enum class PlaySourceType {
        NONE,
        FILE,
        STREAM
    };

    std::unique_ptr<std::thread> playbackThread_;
    std::unique_ptr<std::thread> fileReadThread_;
    std::atomic<bool> isPlaying_{false};
    std::atomic<PlaySourceType> sourceType_{PlaySourceType::NONE};
    
    // 文件播放相关
    std::ifstream audioFile_;
    std::string currentFilePath_;
    int repeatCount_{1}; // 重复播放次数，0表示无限循环
    int initialRepeatCount_{1}; // 保存初始重复次数
    int currentRepeatCount_{0}; // 当前已重复的次数
    std::chrono::system_clock::time_point startPlayTime_; // 开始播放的时间
    std::atomic<int> playbackProgress_{0}; // 播放进度（百分比，0-100）
    std::mutex playInfoMutex_; // 保护播放信息的互斥锁
    
    // 统一的音频数据队列
    std::unique_ptr<El::Utils::BlockingQueue<std::vector<char>>> audioDataQueue_;
};

} // namespace Media
} // namespace El